home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fatted Calf
/
The Fatted Calf.iso
/
Applications
/
Database
/
AddressBook
/
Source
/
AddressView.m
< prev
next >
Wrap
Text File
|
1992-08-20
|
11KB
|
404 lines
/* AddressView.m:
* You may freely copy, distribute, and reuse the code in this example.
* NeXT disclaims any warranty of any kind, expressed or implied, as to its
* fitness for any particular use.
*
* Written by Mai Nguyen, NeXT Developer Support
*
*/
#import <appkit/appkit.h>
#import <objc/List.h>
#import <dbkit/DBRecordList.h>
#import <dbkit/DBValue.h>
#import <libc.h>
#import "AddressView.h"
#import "Controller.h"
#define EMPTY_STRING NXLocalizedString("Cannot accept empty string", NULL, "Notify user that empty string input is not valid.")
static char cellName[100];
@implementation AddressView
- initFrame:(const NXRect *)frameRect
{
NXSize interCellSpacing = {0.0, 0.0}, docSize;
[ super initFrame:frameRect];
cellMatrix = [[Matrix alloc] initFrame:frameRect
mode:NX_LISTMODE
cellClass:[TextFieldCell class]
numRows:0
numCols:1];
/*
* In the following lines,
* remember that "cellMatrix" is the matrix that will be installed
* in the scrollview, "self" is the scrollview.
*/
/* we don't want any space between the matrix's cells */
[cellMatrix setIntercell:&interCellSpacing];
/* resize the matrix to contain the cells */
[cellMatrix sizeToCells];
[cellMatrix setAutosizeCells:YES];
/*
* when the user clicks in the matrix and then drags the mouse out of
* scrollView's contentView, we want the matrix to scroll
*/
[cellMatrix setAutoscroll:YES];
/* let the matrix stretch horizontally */
[cellMatrix setAutosizing:NX_WIDTHSIZABLE];
/* Install the matrix as the docview of the scrollview */
[[self setDocView:cellMatrix] free];
/* set up the visible attributes of the scrollview */
[self setVertScrollerRequired:YES];
[self setBorderType:NX_BEZEL];
/* tell the subviews to resize along with the scrollview */
[self setAutoresizeSubviews:YES];
/* This is the only way to get the clipview to resize too */
[[cellMatrix superview] setAutoresizeSubviews:YES];
/* Allow the scrollview to stretch both horizontally and vertically */
[self setAutosizing:NX_WIDTHSIZABLE|NX_HEIGHTSIZABLE];
/* Resize the matrix to fill the inside of the scrollview */
[self getContentSize:&docSize];
[cellMatrix sizeTo:docSize.width :docSize.height];
/* Set the matrix single click action */
[cellMatrix setTarget:self];
[cellMatrix setAction:@selector(showInfo:)];
/* Allocate DBValue instances for accessing record contents */
aValue = [[DBValue alloc] init];
aValue2 = [[DBValue alloc] init];
return self;
}
- free
{
[cellMatrix free];
if (aValue)
[aValue free];
if (aValue2)
[aValue2 free];
return [super free];
}
- cellMatrix
{
return cellMatrix;
}
/*
* Since we recycle the cells (via renewRows:cols:), we also set the state
* of each cell to 0 and unhighlight it. If we don't do that, the recycled
* cells will display their previous state.
*/
- loadCellsFrom:sender
{
int i, cellCount;
const char *firstName, *lastName;
char buf[100];
DBRecordList * recordList;
List * propertyList;
recordList = (DBRecordList *)[controller getRecordList];
propertyList = (List *)[controller getPropertyList];
cellCount = (int) [controller getRecordCount];
if (cellCount == 0 )
return self;
/* tell the matrix there are 0 cells in it (but don't deallocate them) */
[cellMatrix renewRows:0 cols:1];
[cellMatrix lockFocus]; /* for highlightCellAt::lit: */
for (i=0;i<cellCount;i++) {
TextFieldCell *cell;
/*
* add a row to the matrix. (This doesn't necessarily allocate a new
* cell, thanks to renewRows:cols:).
*/
[cellMatrix addRow];
cell = [cellMatrix cellAt:i:0];
/* make sure the cell is neither selected nor highlighted */
[cellMatrix highlightCellAt:i:0 lit:NO];
[cell setState:0];
/* install the string value in that cell */
[recordList getValue:aValue
forProperty:[propertyList objectAt:1]at:i];
lastName= (const char *)[aValue stringValue];
[recordList getValue:aValue2
forProperty:[propertyList objectAt:2]at:i];
firstName = (const char *)[aValue2 stringValue];
sprintf(buf, "%s %s", lastName, firstName);
[cell setStringValue:buf];
}
[cellMatrix unlockFocus];
[cellMatrix sizeToCells];
[cellMatrix display];
return self;
}
/* Get the newly added row */
- (int) getNewRow
{
int i;
int count, row;
const char* name;
count = [cellMatrix cellCount];
row = count; /* Initialize row to a meaningful number */
for (i = 0; i < count; i++) {
name = [[cellMatrix cellAt:i:0] stringValue];
if (!strcmp(cellName, name) ) {
row = i;
break;
}
}
return row;
}
/* Show the information contained in each selected record
*/
- showInfo:sender
{
int index;
DBRecordList * recordList;
List * propertyList;
recordList = [controller getRecordList];
propertyList = [controller getPropertyList];
index = [cellMatrix selectedRow];
/* Find the person's id */
[recordList getValue:aValue forProperty:[propertyList objectAt:0]at:index];
[ssnField setStringValue:(const char *)[aValue stringValue]];
/* Find the person's last name and first name */
[recordList getValue:aValue forProperty:[propertyList objectAt:1]at:index];
[lnameField setStringValue: (const char *)[aValue stringValue]];
[recordList getValue:aValue forProperty:[propertyList objectAt:2]at:index];
[fnameField setStringValue:(const char *)[aValue stringValue]];
/* Find the person's phone number */
[recordList getValue:aValue forProperty:[propertyList objectAt:3]at:index];
[phoneField setStringValue:(const char *)[aValue stringValue]];
/* Find the person's address */
[recordList getValue:aValue forProperty:[propertyList objectAt:4]at:index];
[addressField setStringValue:(const char *)[aValue stringValue]];
/* Find the person's city of residence */
[recordList getValue:aValue forProperty:[propertyList objectAt:5]at:index];
[cityField setStringValue:(const char *)[aValue stringValue]];
/* Find the person's state of residence */
[recordList getValue:aValue forProperty:[propertyList objectAt:6]at:index];
[stateField setStringValue:(const char *)[aValue stringValue]];
/* Find the person's zip code */
[recordList getValue:aValue forProperty:[propertyList objectAt:7]at:index];
[zipField setStringValue:(const char *)[aValue stringValue]];
return self;
}
/* Add a new record at the specified index.
*/
- addRecordFrom:sender at:(unsigned)index
{
DBRecordList * recordList;
List * propertyList;
recordList = (DBRecordList *)[controller getRecordList];
propertyList = (List *)[controller getPropertyList];
/* In order to get records in and out,
* we must use a value object all the time
*/
/* add empty record */
[recordList insertRecordAt:index];
if ([self setNewRecordFrom:sender at:index] == nil) {
return nil;
}
if ([recordList saveModifications] == 0)
return self;
return nil;
}
/* Update the record specified at index.
*/
- updateRecordFrom:sender at:(unsigned) index
{
DBRecordList * recordList;
List * propertyList;
recordList = (DBRecordList *)[controller getRecordList];
propertyList = (List *) [controller getPropertyList];
if ([self setNewRecordFrom:sender at:index] == nil) {
return nil;
}
if ([recordList saveModifications] == 0)
return self;
return nil;
}
/* Get the user input from the text fields. Note that if a field is empty,
* the operation (either insert or update) would fail. Also, for simplicity,
* an arbitrary contract number is assigned to new records.
*/
- setNewRecordFrom:sender at:(unsigned)index
{
DBRecordList *aRecList;
List *aPropList;
const char *inputString;
const char *lastName;
aRecList = (DBRecordList *)[controller getRecordList];
aPropList = (List *)[controller getPropertyList];
/* get the ssn or author id */
inputString = (const char *)[ssnField stringValue];
/* If the string is empty, abort the operation */
if ( !strcmp(inputString,"")){
NXRunAlertPanel (NULL,EMPTY_STRING,NULL, NULL, NULL);
return nil;
}
else {
[aValue setStringValue:inputString];
[aRecList setValue:aValue forProperty:[aPropList objectAt:0] at:index];
}
/* set last name */
lastName = (const char *)[lnameField stringValue];
if ( !strcmp(lastName,"")){
NXRunAlertPanel (NULL,EMPTY_STRING,NULL, NULL, NULL);
return nil;
}
else {
[aValue setStringValue:lastName];
[aRecList setValue:aValue forProperty:[aPropList objectAt:1] at:index];
}
/* set first name */
inputString = (const char *)[fnameField stringValue];
if ( !strcmp(inputString,"")){
NXRunAlertPanel (NULL, EMPTY_STRING, NULL, NULL, NULL);
return nil;
}
else {
[aValue setStringValue:(const char *)inputString];
[aRecList setValue:aValue forProperty:[aPropList objectAt:2] at:index];
sprintf( cellName, "%s %s", lastName, inputString);
}
/* set phone number */
inputString = (const char *)[phoneField stringValue];
if ( !strcmp(inputString,"")){
NXRunAlertPanel (NULL,EMPTY_STRING,NULL, NULL, NULL);
return nil;
}
else {
[aValue setStringValue: inputString];
[aRecList setValue:aValue forProperty:[aPropList objectAt:3] at:index];
}
/* set address */
inputString = (const char *)[addressField stringValue];
if ( !strcmp(inputString,"")){
NXRunAlertPanel (NULL,EMPTY_STRING,NULL, NULL, NULL);
return nil;
}
else {
[aValue setStringValue: inputString];
[aRecList setValue:aValue forProperty:[aPropList objectAt:4] at:index];
}
/* set city name */
inputString = (const char *)[cityField stringValue];
if ( !strcmp(inputString,"")){
NXRunAlertPanel (NULL,EMPTY_STRING,NULL, NULL, NULL);
return nil;
}
else {
[aValue setStringValue: inputString];
[aRecList setValue:aValue forProperty:[aPropList objectAt:5] at:index];
}
/* set state */
inputString = (const char *)[stateField stringValue];
if ( !strcmp(inputString,"")){
NXRunAlertPanel (NULL,EMPTY_STRING,NULL, NULL, NULL);
return nil;
}
else {
[aValue setStringValue: inputString];
[aRecList setValue:aValue forProperty:[aPropList objectAt:6] at:index];
}
/* set zip code */
inputString = (const char *)[zipField stringValue];
if ( !strcmp(inputString,"")){
NXRunAlertPanel (NULL,EMPTY_STRING,NULL, NULL, NULL);
return nil;
}
else {
[aValue setStringValue: inputString];
[aRecList setValue:aValue forProperty:[aPropList objectAt:7] at:index];
}
/* assign an arbitrary contract number 1 to the new record */
[aRecList getValue:aValue forProperty:[aPropList objectAt:8] at:index];
if ( ![aValue intValue]) {
[aValue setIntValue:1];
[aRecList setValue:aValue forProperty:[aPropList objectAt:8] at:index];
}
return self;
}
- deleteSelectedRecord:sender
{
int row;
DBRecordList * recordList;
row = [cellMatrix selectedRow];
recordList = (DBRecordList *)[controller getRecordList];
[recordList deleteRecordAt:row];
if ([recordList saveModifications] == 0)
return self;
else
return nil;
}
@end